protected function resolveContainerPath( $container, $relStoragePath ) {
if ( !mb_check_encoding( $relStoragePath, 'UTF-8' ) ) {
return null; // not UTF-8, makes it hard to use CF and the swift HTTP API
- } elseif ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
+ } elseif ( strlen( rawurlencode( $relStoragePath ) ) > 1024 ) {
return null; // too long for Swift
}
* @param array $params
* @return array Sanitized value of 'headers' field in $params
*/
+ protected function sanitizeHdrsStrict( array $params ) {
+ if ( !isset( $params['headers'] ) ) {
+ return [];
+ }
+
+ $headers = $this->getCustomHeaders( $params['headers'] );
+ unset( $headers[ 'content-type' ] );
+
+ return $headers;
+ }
+
+ /**
+ * Sanitize and filter the custom headers from a $params array.
+ * Only allows certain "standard" Content- and X-Content- headers.
+ *
+ * When POSTing data, libcurl adds Content-Type: application/x-www-form-urlencoded
+ * if Content-Type is not set, which overwrites the stored Content-Type header
+ * in Swift - therefore for POSTing data do not strip the Content-Type header (the
+ * previously-stored header that has been already read back from swift is sent)
+ *
+ * @param array $params
+ * @return array Sanitized value of 'headers' field in $params
+ */
protected function sanitizeHdrs( array $params ) {
return isset( $params['headers'] )
? $this->getCustomHeaders( $params['headers'] )
// Normalize casing, and strip out illegal headers
foreach ( $rawHeaders as $name => $value ) {
$name = strtolower( $name );
- if ( preg_match( '/^content-(type|length)$/', $name ) ) {
+ if ( preg_match( '/^content-length$/', $name ) ) {
continue; // blacklisted
} elseif ( preg_match( '/^(x-)?content-/', $name ) ) {
$headers[$name] = $value; // allowed
'etag' => md5( $params['content'] ),
'content-type' => $contentType,
'x-object-meta-sha1base36' => $sha1Hash
- ] + $this->sanitizeHdrs( $params ),
+ ] + $this->sanitizeHdrsStrict( $params ),
'body' => $params['content']
] ];
'etag' => md5_file( $params['src'] ),
'content-type' => $contentType,
'x-object-meta-sha1base36' => $sha1Hash
- ] + $this->sanitizeHdrs( $params ),
+ ] + $this->sanitizeHdrsStrict( $params ),
'body' => $handle // resource
] ];
'headers' => [
'x-copy-from' => '/' . rawurlencode( $srcCont ) .
'/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
- ] + $this->sanitizeHdrs( $params ), // extra headers merged into object
+ ] + $this->sanitizeHdrsStrict( $params ), // extra headers merged into object
] ];
$method = __METHOD__;
'headers' => [
'x-copy-from' => '/' . rawurlencode( $srcCont ) .
'/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
- ] + $this->sanitizeHdrs( $params ) // extra headers merged into object
+ ] + $this->sanitizeHdrsStrict( $params ) // extra headers merged into object
]
];
if ( "{$srcCont}/{$srcRel}" !== "{$dstCont}/{$dstRel}" ) {
}
}
- $this->logger->error( __METHOD__ . ": unable to set SHA-1 metadata for $path" );
+ $this->logger->error( __METHOD__ . ': unable to set SHA-1 metadata for {path}',
+ [ 'path' => $path ] );
return $objHdrs; // failed
}
if ( $rcode != 204 && $rcode !== 202 ) {
$status->fatal( 'backend-fail-internal', $this->name );
- $this->logger->error( __METHOD__ . ': unexpected rcode value (' . $rcode . ')' );
+ $this->logger->error( __METHOD__ . ': unexpected rcode value ({rcode})',
+ [ 'rcode' => $rcode ] );
}
return $status;
if ( $code == 401 ) { // possibly a stale token
$this->srvCache->delete( $this->getCredsCacheKey( $this->swiftUser ) );
}
- $this->logger->error(
- "HTTP $code ($desc) in '{$func}' (given '" . FormatJson::encode( $params ) . "')" .
- ( $err ? ": $err" : "" )
- );
+ $msg = "HTTP {code} ({desc}) in '{func}' (given '{params}')";
+ $msgParams = [
+ 'code' => $code,
+ 'desc' => $desc,
+ 'func' => $func,
+ 'req_params' => FormatJson::encode( $params ),
+ ];
+ if ( $err ) {
+ $msg .= ': {err}';
+ $msgParams['err'] = $err;
+ }
+ $this->logger->error( $msg, $msgParams );
}
}